package com.sardine.base.utils;

import org.dom4j.*;
import org.dom4j.io.*;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


/****
 * 读取文档
 * @author daif
 *
 */
public class XMLUtil {
	
	/***
	 * 从文件读取XML，输入文件名称，返回XML文档
	 * @param fileName
	 * @return
	 * @throws DocumentException
	 */
	public Document read(String fileName) throws DocumentException
	{
		SAXReader reader=new SAXReader();
		Document document=reader.read(new File(fileName));
		return document;
	}
	
	/***
	 * 从文件读取XML，输入文件名称，返回XML文档
	 * @param inputStream
	 * @return
	 * @throws DocumentException
	 */
	public Document read(InputStream inputStream) throws DocumentException
	{
		SAXReader reader=new SAXReader();
		Document document=reader.read(inputStream);
		return document;
	}
	
	/***
	 * 得到ROOT节点，一切解析、分析都是从root元素开始的
	 * @param doc
	 * @return
	 */
	public Element getRootElement(Document doc){
		return doc.getRootElement();
	}
	
	/***
	 * 枚举方式解析---遍历节点
	 * 
	 * @param root
	 */
	public void annlyticalXML(Element root){
		//TODO 该方法需要继续完善
		//枚举所有子节点
		for(Iterator i=root.elementIterator();i.hasNext();){
			Element element=(Element)i.next();
		}
		//枚举名称为 foo 的节点
		for(Iterator i=root.elementIterator("foo");i.hasNext();){
			Element element=(Element)i.next();
		}
		
		//枚举属性
		for(Iterator i=root.attributeIterator();i.hasNext();){
			Attribute attribute=(Attribute)i.next();
		}
	}
	
	/***
	 * 递归方式解析---遍历节点
	 * 
	 * @param root
	 */
	public void treeWalk(Element root){
		for(Iterator i=root.nodeIterator();i.hasNext();){
			Node node=(Node)i.next();
			if(node instanceof Element){
				System.out.println(node.getName());
				treeWalk((Element)node);
			}else
			{
				//do something....
			}
		}
	}
	
	
	/***
	 * 递归方式 查找Element
	 * 
	 * @param root
	 */
	public Element findElement(Element root,String elementName,Map<String,String> attributes){
		Element element=null;
		for(Iterator i=root.nodeIterator();i.hasNext();){
			Node node=(Node)i.next();
			if(node instanceof Element){
				if(elementName.equals(node.getName())){
					element=(Element)node;
					if(attributes!=null){
						boolean bool=	findAttributeFromElement(element,attributes);
						if(bool){
							break;
						}else
						{
							element=null;
						}
					}
					if(element!=null){
						break;
					}
				}else
				{
					element=findElement((Element)node,elementName,attributes);
					if(element!=null){
						break;
					}
				}
				
			}else
			{
				//do something....
			}
		}
		return element;
	}
	
	/****
	 * 判断当前节点，是否拥有指定属性和值
	 * @param element
	 * @param attributes
	 * @return
	 */
	public boolean findAttributeFromElement(Element element,Map<String,String> attributes){
		boolean bool=false;
		int size=attributes.size();
		int countBool=0;
		//枚举属性
		for(Iterator i=element.attributeIterator();i.hasNext();){
			
			Attribute attributeTemp=(Attribute)i.next();
			
			String value=attributes.get(attributeTemp.getName());
			
			if(attributeTemp.getValue().equals(value)){
				countBool++;
			}
		}
		//是否相等
		if(size==countBool){
			bool=true;
		}
		return bool;
	}
	
	/***
	 * visitor 模式遍历
	 * @param root
	 */
	public void visitor(Element root){
		root.accept(new Visitor(){
			@Override
			public void visit(Document arg0) {
				// TODO Auto-generated method stub
			}
			@Override
			public void visit(DocumentType arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(Element arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(Attribute arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(CDATA arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(Comment arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(Entity arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(Namespace arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(ProcessingInstruction arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void visit(Text arg0) {
				// TODO Auto-generated method stub
			}});
	}
	
	/***
	 * XPath 
	 * 访问HTML中的所有的超链接
	 * @param document
	 */
	public void barXPathLink(Document document)
	{
		List list=document.selectNodes("//a/@href");
		for(Iterator i=list.iterator();i.hasNext();){
			Attribute attribute=(Attribute)i.next();
			String url=attribute.getValue();
		}
	}
	/***
	 * XPath 
	 * 访问一个节点，
	 * @param document
	 */
	public void barXPath(Document document)
	{
		List list=document.selectNodes("//foo/bar");
		Node node=document.selectSingleNode("//foo/bar/author");
		String name=node.valueOf("@name");
	}
	/***
	 * 字符串转换为XML
	 * @throws DocumentException 
	 */
	public static Document String2XML(String xmlStr) throws DocumentException{
		return DocumentHelper.parseText(xmlStr);
	}
	/***
	 * XML转换为字符串
	 * @throws DocumentException 
	 */
	public String XML2String(Document document){
		return document.asXML();
	}
	
	/***
	 * 用XSLT转换XML
	 * @param document
	 * @param stylesheet
	 * @return
	 * @throws TransformerException
	 */
	public Document styleDocument(Document document,String stylesheet) throws TransformerException
	{
		//加载 Transformer 使用JAXP
		TransformerFactory transformerFactory= TransformerFactory.newInstance();
		Transformer transformer=transformerFactory.newTransformer(new StreamSource(stylesheet));
		//now lets style the given docuemnt
		DocumentSource xmlSource=new DocumentSource(document);
		DocumentResult result=new DocumentResult();
		transformer.transform(xmlSource, result);
		Document transformeredDoc= result.getDocument();
		return transformeredDoc;
	}
	
	/***
	 * 
	 * @param element
	 * @param attributeMap
	 */
	public static void addAttribute(Element element,Map<String,String> attributeMap){
		for(Entry<String,String> entry:attributeMap.entrySet()){
			element.addAttribute(entry.getKey(), entry.getValue());
		}
	}
	
	
	/***
	 * 创建XML文件
	 * @return
	 */
	public Document createDocument()
	{
		Document document=	DocumentHelper.createDocument();
		Element root=document.addElement("w:document");
		root.addNamespace("ve", "http://schemas.openxmlformats.org/markup-compatibility/2006");
		root.addNamespace("o", "urn:schemas-microsoft-com:office:office");
		root.addNamespace("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
		root.addNamespace("m","http://schemas.openxmlformats.org/officeDocument/2006/math");
		root.addNamespace("v", "urn:schemas-microsoft-com:vml");
		root.addNamespace("wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing");
		root.addNamespace("w10", "urn:schemas-microsoft-com:office:word");
		root.addNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
		root.addNamespace("wne","http://schemas.microsoft.com/office/word/2006/wordml");
		return document;
	}
	
	/***
	 * 文件输出
	 * @param document xml 文档
	 * @param path 输出路径
	 * @param isCompact 是否压缩
	 * @throws IOException
	 */
	public void outPutFile(Document document,String path,boolean isCompact) throws IOException
	{
		FileOutputStream fos=new FileOutputStream(path);
		OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");
		//缩减格式
		OutputFormat format=null;
		if(isCompact){
			format=OutputFormat.createCompactFormat();
		}else
		{
			format=OutputFormat.createPrettyPrint();
		}
		format.setEncoding("UTF-8");
		XMLWriter writer= new XMLWriter(osw,format);
		writer.write(document);
		writer.flush();
		osw.close();
		writer.close();
	}
	/***
	 * 压缩模式输出
	 * @param document
	 * @param path
	 * @throws IOException
	 */
	public void outPutFile(Document document,String path) throws IOException
	{
		outPutFile(document, path,true);
	}
}
